package com.dinim.matrix;


import com.dinim.math.NumberUtil;




public class Matrix implements Cloneable{

	/**
	 * I = LINE
	 * J = ROW
	 */
	
	private double[][] matrix;
	
	public Object clone() throws CloneNotSupportedException{
		Object o = super.clone();
		((Matrix)o).matrix = this.matrix.clone();
		for(int i = 0; i < matrix.length; i++){
			((Matrix)o).matrix[i] = this.matrix[i].clone();
		}
		return o;
	}

	public String toString() {		
		String text = "";
		for (int i = 0; i < matrix.length; i++) {
			text = text + "|";
			for (int j = 0; j < matrix[0].length; j++) {
				text = text + NumberUtil.cutDigits(this.matrix[i][j], 2) + " ; ";
			}
			text = text.substring(0, text.length()-3);
			text = text + "|\n";
		}
		return text;
	}
	
	public Matrix(int i, int j) {
		this.matrix = new double[i][j];
	}

	public Matrix(double[][] matrix){
		this.matrix = matrix;
	}
	
	public double[][] getMatrixArray(){
		return this.matrix.clone();
	}
	
	public void setLine(double[] values, int line){		
		try{
			for(int i = 0; i < values.length; i++){
				matrix[line][i] = values[i];
			}
		}catch (IndexOutOfBoundsException e){
			e.printStackTrace();
		}
	}
	
	public void setRow(double[] values, int row){		
		try{
			for(int i = 0; i < values.length; i++){
				matrix[i][row] = values[i];
			}
		}catch (IndexOutOfBoundsException e){
			e.printStackTrace();
		}
	}
	
	public double get(int i, int j){		
		try {
			return this.matrix[i][j];
		} catch (IndexOutOfBoundsException e) {
			e.printStackTrace();
			return -1;
		}		
	}
	
	public void set(int line, int row, double value){		
		try {
			this.matrix[line][row] = value;
		} catch (IndexOutOfBoundsException e) {
			e.printStackTrace();
		}
	}

	public int getLengthI(){		
		return this.matrix.length;
	}
	
	public int getLengthJ(){		
		return this.matrix[0].length;
	}

	public boolean similarDimensions(Matrix matrix){
		if((this.getLengthI() == matrix.getLengthI()) && 
		   (this.getLengthJ() == matrix.getLengthJ())) 
			return true;
		else 
			return false;
	}

	public void multiplyByMatrix(Matrix leftMatrix){

		Matrix rightMatrix = new Matrix(this.getMatrixArray());
		
		for(int j = 0; j < rightMatrix.getLengthJ(); j++){			
			double[] rightMatrixColumn = new double[rightMatrix.getLengthI()];
			for(int u = 0; u < rightMatrixColumn.length; u++){
				rightMatrixColumn[u] = rightMatrix.get(u, j);
			}			

			for(int i = 0; i < leftMatrix.getLengthI(); i++){					
				double[] leftMatrixLine = new double[leftMatrix.getLengthJ()];					
				for(int u = 0; u < leftMatrixLine.length; u++){
					leftMatrixLine[u] = leftMatrix.get(i, u);	
				}	
				
				this.set(i, j, 0);
				for(int pair = 0; pair < leftMatrixLine.length; pair++){
					this.set(i, j, this.get(i, j) + leftMatrixLine[pair] * rightMatrixColumn[pair]);
				}
			}				
		}
	}
}
